package live.jialing.sip.base.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import live.jialing.authz.domain.SecurityGroup;
import live.jialing.authz.service.SecurityGroupService;
import live.jialing.core.data.LinkType;
import live.jialing.core.data.jpa.CustomJpaRepository;
import live.jialing.core.exception.ServiceException;
import live.jialing.core.service.BaseDomainService;
import live.jialing.core.service.GeneralService;
import live.jialing.data.util.SpecificationUtil;
import live.jialing.sip.base.dict.SchoolRoleEnum;
import live.jialing.sip.base.domain.GradeGroup;
import live.jialing.sip.base.domain.School;
import live.jialing.sip.base.domain.Squad;
import live.jialing.sip.base.domain.Student;
import live.jialing.sip.base.repository.ClassRepository;
import live.jialing.util.general.Collections3;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 班
 */
@Service
public class ClassService extends BaseDomainService<Squad, Long> implements GeneralService<Squad, Long> {

    private static Logger logger = LoggerFactory.getLogger(ClassService.class);

    @Resource
    private SchoolService schoolService;

    @Resource
    private ClassRepository classRepository;

    @Resource
    private StudentService studentService;

    @Resource
    private SecurityGroupService securityGroupService;

    @Resource
    private GradeService gradeService;

    @Override
    public CustomJpaRepository getRepository() {
        return this.classRepository;
    }

    public Specification<Squad> buildSpecification(java.lang.Class<Squad> classz, Map<String, Object> searchParams, LinkType type) {

        return SpecificationUtil.buildSpecification(classz, searchParams, type);
    }


    // TODO 学生转班、退学、休学

    /**
     * 班级添加新学生
     *
     * @param classId
     * @param students
     */
    @Transactional
    public void addStudent(long classId, List<Student> students) {

        if (Collections3.isEmpty(students)) {
            throw new ServiceException("学生集合为空！");
        }

        Squad cls = this.findByPK(classId);
        if (cls == null) {
            throw new ServiceException("班级ID不正确，没有该班级");
        }

        School school = schoolService.findByPK(cls.getSchool().getId());

        students.forEach(s -> {
            s.setSchool(school);
            s.setSquad(cls);
        });

        studentService.batchAdd(students);
    }

    /**
     * 年级毕业
     *
     * @param schoolId 学校ID
     * @param grade    入学年份
     * @see live.jialing.sip.base.dict.ClassStatusEnum
     */
    @Transactional
    public void graduate(long schoolId, int grade) {

        if (schoolId < 1 || grade < 2000) {
            logger.warn("参数错误：schoolId={}，grade={}", schoolId, grade);
            return;
        }

        classRepository.graduate(schoolId, grade);
    }

    /**
     * 获取老师所加入的班级
     *
     * @param schoolId  学校id
     * @param teacherId 老师id
     * @return 班级集合
     */
    public List<Squad> findClassByTeacher(long schoolId, long teacherId) {

        if (schoolId < 1 || teacherId < 1) {
            logger.warn("参数错误：schoolId={}，teacherId={}", schoolId, teacherId);
            return Lists.newArrayList();
        }

        Map<String, Object> searchParams = Maps.newTreeMap();
        searchParams.put("EQ_school.id", schoolId);
        searchParams.put("EQ_teachers.id", teacherId);
        return this.findAll(searchParams, null);
    }

    /**
     * 获取员工能够查看的班级，校长看全校、年级主任看年级、班主任/老师看本班
     * <p>
     *     此数据权限获取待定
     * </p>
     * @param schoolId   学校ID
     * @param employeeId 员工ID
     * @return 班级集合
     */
    public List<Squad> findClassByEmployee(long schoolId, long employeeId) {

        // 获取角色
        List<SecurityGroup> securityGroups = securityGroupService.findValidSecurityGroupByAccount(schoolId, employeeId);
        // 判断是不是校长
        Optional<SecurityGroup> securityGroup = securityGroups.stream().filter(sg -> StringUtils.equals(sg.getCode(), SchoolRoleEnum.SCH_MASTER.toString())).findAny();
        if (securityGroup.isPresent()) {
            // 返回全校在读的班
            return classRepository.findBySchool(schoolId);
        }

        List<Squad> squads = Lists.newArrayList();
        // 年级主任
        securityGroup = securityGroups.stream().filter(sg -> StringUtils.equals(sg.getCode(), SchoolRoleEnum.SCH_GRADE_MASTER.toString())).findAny();
        if (securityGroup.isPresent()) {
            // 获取所在的年级
            List<GradeGroup> gradeGroups = gradeService.findGradeGroup(schoolId, employeeId);
            if(Collections3.isNotEmpty( gradeGroups)){
                gradeGroups.forEach(g->{
                    // 返回改年级的班
                    List<Squad> squadList = classRepository.findBySchoolAndGrade(schoolId, g.getGrade());
                    if (Collections3.isNotEmpty(squadList)) {
                        squads.addAll(squadList);
                    }
                });
            }
        }

        // 班主任
        List<Squad> squadList = this.findClassByTeacher(schoolId, employeeId);
        if (Collections3.isNotEmpty(squadList)) {
            squads.addAll(squadList);
        }

        return squads.stream().distinct().collect(Collectors.toList());
    }
}
